package project.gc.com.myapplication;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

/**
 * @Dizner 2018-08-28
 * 水平尺工具
 */
public class LevelRulerView extends View implements SensorEventListener {

    private float width;
    private float height;
    Paint centerPaint;
    Paint ovalPaint;
    Paint linePaint;
    Paint runLinePaint;
    float angle;
    float elevationAngle;//仰角

    private float pointCenterX, pointCenterY;

    private String TAG = getClass().getSimpleName();
    private RectF oval; //中心圆弧的范围

    private float maxErrorValue = 1.5f; //最大误差值

    private int maxAngle = 45;//最大角度
    private int maxElevationAngle = 70;//最大仰角角度
    private int ovaLinelWidth = 50;//弧线的宽度
    private int runLineWidth = 4;//水平线的宽度
    private int centerLineWidth = 6;//十字准星的宽度
    private int centerLineSizeWidth = 100;//十字准星的长度
    private int verticalineHeght = 200;//竖线的高度


    private int ovalColor = Color.parseColor("#5c000000"); //弧线颜色
    private int runLineColor = Color.YELLOW;//水平线颜色
    private int runLineSelectedColor = Color.GREEN;//水平线选中颜色
    private int centerLineColor = Color.GRAY;//十字准星线颜色
    private int baseLineColor = Color.parseColor("#ffffff");//基准线颜色

    private SensorManager sensorManager; //传感器服务


    private Sensor acc_sensor;
    private Sensor mag_sensor;
    private float ovalWidth;
    private float ovalHeight;


    public LevelRulerView(Context context) {
        this(context, null);
        init(context);
    }

    public LevelRulerView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
        init(context);
    }

    public LevelRulerView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        TypedArray style = context.obtainStyledAttributes(attrs, R.styleable.LevelRulerView, defStyle, 0);
        ovalColor = style.getColor(R.styleable.LevelRulerView_ovalColor, Color.parseColor("#5c000000"));
        runLineColor = style.getColor(R.styleable.LevelRulerView_runLineColor, Color.YELLOW);
        runLineSelectedColor = style.getColor(R.styleable.LevelRulerView_runLineSelectedColor, Color.GREEN);
        centerLineColor = style.getColor(R.styleable.LevelRulerView_centerLineColor, Color.GRAY);
        baseLineColor = style.getColor(R.styleable.LevelRulerView_baseLineColor, Color.parseColor("#ffffff"));
        maxAngle = style.getInteger(R.styleable.LevelRulerView_maxAngle, 45);
        maxElevationAngle = style.getInteger(R.styleable.LevelRulerView_maxElevationAngle, 70);
        ovaLinelWidth = style.getDimensionPixelOffset(R.styleable.LevelRulerView_ovalWidth, 50);
        runLineWidth = style.getDimensionPixelOffset(R.styleable.LevelRulerView_runLineWidth, 4);
        centerLineWidth = style.getDimensionPixelOffset(R.styleable.LevelRulerView_centerLineWidth, 6);
        maxErrorValue = style.getFloat(R.styleable.LevelRulerView_maxErrorValue, 1.5f);
        init(context);
    }

    private void init(Context context) {
        sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);


        centerPaint = new Paint();
        centerPaint.setStyle(Paint.Style.STROKE);
        centerPaint.setColor(centerLineColor);
        centerPaint.setStrokeWidth(centerLineWidth);
        ovalPaint = new Paint();
        ovalPaint.setStyle(Paint.Style.STROKE);
        ovalPaint.setStrokeWidth(ovaLinelWidth);
        ovalPaint.setColor(ovalColor);
        linePaint = new Paint();
        linePaint.setStyle(Paint.Style.STROKE);
        linePaint.setStrokeWidth(runLineWidth);
        linePaint.setColor(baseLineColor);
        runLinePaint = new Paint();
        runLinePaint.setStyle(Paint.Style.STROKE);
        runLinePaint.setStrokeWidth(runLineWidth);
        runLinePaint.setColor(runLineColor);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        this.width = getMeasuredWidth();
        this.height = getMeasuredHeight();
        pointCenterX = width / 2;
        pointCenterY = height / 2;
        float x = (width - height / 2) / 2;
        float y = height / 4;

        ovalWidth = width - x - x;
        ovalHeight = height - y - y;
        verticalineHeght = (int) (ovalHeight / 2);
        centerLineSizeWidth = (int) (ovalHeight / 4);
        oval = new RectF(x, y,
                width - x, height - y);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (maxAngle > 90) {
            throw new IllegalArgumentException("The maximum angle is out of range, the maximum is 90.");
        }
        //绘制外层圆弧
        canvas.drawArc(oval, 180 - maxAngle, maxAngle * 2, false, ovalPaint);
        canvas.drawArc(oval, maxAngle, -maxAngle * 2, false, ovalPaint);
        //绘制十字准星
        canvas.drawLine(pointCenterX - centerLineSizeWidth / 2, pointCenterY, pointCenterX + centerLineSizeWidth / 2, pointCenterY, centerPaint);
        canvas.drawLine(pointCenterX, pointCenterY - centerLineSizeWidth / 2, pointCenterX, pointCenterY + centerLineSizeWidth / 2, centerPaint);
        //绘制两条竖线
        canvas.drawLine(pointCenterX - ovalWidth / 4, pointCenterY - verticalineHeght / 2, pointCenterX - ovalWidth / 4, pointCenterY + verticalineHeght / 2, ovalPaint);
        canvas.drawLine(pointCenterX + ovalWidth / 4, pointCenterY - verticalineHeght / 2, pointCenterX + ovalWidth / 4, pointCenterY + verticalineHeght / 2, ovalPaint);
        //绘制两条竖线上的基准线
        canvas.drawLine(pointCenterX - ovalWidth / 4 - ovaLinelWidth / 2, pointCenterY, pointCenterX - ovalWidth / 4 + ovaLinelWidth / 2, pointCenterY, linePaint);
        canvas.drawLine(pointCenterX + ovalWidth / 4 - ovaLinelWidth / 2, pointCenterY, pointCenterX + ovalWidth / 4 + ovaLinelWidth / 2, pointCenterY, linePaint);
        //绘制两条弧线上的基准线
        canvas.drawLine(width / 2 - ovalWidth / 2 - ovaLinelWidth / 2, pointCenterY, width / 2 - ovalWidth / 2 + ovaLinelWidth / 2, pointCenterY, linePaint);
        canvas.drawLine(width / 2 + ovalWidth / 2 - ovaLinelWidth / 2, pointCenterY, width / 2 + ovalWidth / 2 + ovaLinelWidth / 2, pointCenterY, linePaint);


        //处理水平角度，水平角度范围限制
        if (angle > maxAngle) {
            angle = maxAngle;
        } else if (angle < -maxAngle) {
            angle = -maxAngle;
        }

        //过滤超出范围的数据 范围：0 ~ 180
        if (elevationAngle < 0 && elevationAngle > -90) {
            elevationAngle = 0;
        } else if (elevationAngle >= -180 && elevationAngle < -90) {
            elevationAngle = 180;
        }

        //处理仰角 输入值（0 ~ 180）输出值（-90 ~ +90）
        elevationAngle = elevationAngle - 90;
        //仰角范围限制
        if (elevationAngle > maxElevationAngle) {
            elevationAngle = maxElevationAngle;
        } else if (elevationAngle < -maxElevationAngle) {
            elevationAngle = -maxElevationAngle;
        }

        //误差计算-是否在允许范围内
        if (Math.abs(angle) <= maxErrorValue && Math.abs(elevationAngle) <= maxErrorValue) {
            runLinePaint.setColor(runLineSelectedColor);
        } else {
            runLinePaint.setColor(runLineColor);
        }


//        Log.i(TAG + "-elevationAngle", elevationAngle + "");


        float ty = elevationAngle * verticalineHeght / (maxElevationAngle * 2);

        canvas.drawLine(pointCenterX - ovalWidth / 4 - ovaLinelWidth / 2, pointCenterY + ty, pointCenterX - ovalWidth / 4 + ovaLinelWidth / 2, pointCenterY + ty, runLinePaint);
        canvas.drawLine(pointCenterX + ovalWidth / 4 - ovaLinelWidth / 2, pointCenterY + ty, pointCenterX + ovalWidth / 4 + ovaLinelWidth / 2, pointCenterY + ty, runLinePaint);


        canvas.rotate(angle, width / 2, height / 2);
        canvas.drawLine(0, height / 2, width / 2 - ovalWidth / 2 + ovaLinelWidth / 2, height / 2, runLinePaint);
        canvas.drawLine(width / 2 + ovalWidth / 2 - ovaLinelWidth / 2, height / 2, width, height / 2, runLinePaint);
    }

    private float[] accValues = new float[3];
    private float[] magValues = new float[3];
    // 旋转矩阵，用来保存磁场和加速度的数据
    private float r[] = new float[9];
    // 模拟方向传感器的数据（原始数据为弧度）
    private float values[] = new float[3];

    @Override
    public void onSensorChanged(SensorEvent event) {
//        y = (Math.abs(event.values[1]) > 0.9 ? event.values[1] - 0.7f : event.values[1]) * 10;

        int sensorType = event.sensor.getType();
        switch (sensorType) {
            case Sensor.TYPE_ACCELEROMETER:
                accValues = event.values.clone();
                break;
            case Sensor.TYPE_MAGNETIC_FIELD:
                magValues = event.values.clone();
                break;

        }

        SensorManager.getRotationMatrix(r, null, accValues, magValues);
        SensorManager.getOrientation(r, values);

        // 获取　沿着Z轴转过的角度
        float azimuth = values[0];

        // 获取　沿着X轴倾斜时　与Y轴的夹角
        float pitchAngle = values[1];

        // 获取　沿着Y轴的滚动时　与X轴的角度
        //此处与官方文档描述不一致，所在加了符号（https://developer.android.google.cn/reference/android/hardware/SensorManager.html#getOrientation(float[], float[])）
        float rollAngle = -values[2];

        angle = (float) Math.toDegrees(pitchAngle);
        elevationAngle = (float) Math.toDegrees(rollAngle);
//        Log.e(TAG, values[0] + "//" + values[1] + "//" + values[2]);
//        Log.e(TAG, angle + "");
        invalidate();
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
    }

    public void onResume() {
        // 给传感器注册监听：
        acc_sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        mag_sensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
        sensorManager.registerListener(this, acc_sensor, SensorManager.SENSOR_DELAY_UI);
        sensorManager.registerListener(this, mag_sensor, SensorManager.SENSOR_DELAY_UI);
    }

    protected void onPause() {
        sensorManager.unregisterListener(this);
    }
}
